#include <sstream>
#include <fstream>
#include "Poco/Dynamic/Var.h"
#include "Poco/JSON/Object.h"
#include "Poco/JSON/Array.h"
#include "Poco/JSON/Parser.h"
#include "Poco/JSON/Object.h"
#include "Poco/JSON/Query.h"
#include "JsonDoc.h"

using namespace SystemTool;

#define Trans(Obj,NewType) (NewType*)Obj

// Empty construction
JsonDocument::JsonDocument() : m_pJsonObj(nullptr), m_pJsonDoc(nullptr), m_pJsonArr(nullptr), m_pErrMsg(nullptr)
{
    m_pJsonObj = new Poco::Dynamic::Var;
    m_pJsonDoc = new Poco::JSON::Object;
    m_pJsonArr = new Poco::JSON::Array;
    m_pErrMsg = new std::string;
}

// Destruct json
JsonDocument::~JsonDocument()
{
    if(m_pErrMsg)
    {
        delete m_pErrMsg;
        m_pErrMsg = nullptr;
    }

    if(m_pJsonObj)
    {
        delete Trans(m_pJsonObj,Poco::Dynamic::Var);
        m_pJsonObj = nullptr;
    }

    if(m_pJsonDoc)
    {
        delete Trans(m_pJsonDoc,Poco::JSON::Object);
        m_pJsonDoc = nullptr;
    }

    if(m_pJsonArr)
    {
        delete Trans(m_pJsonArr,Poco::JSON::Array);
        m_pJsonArr = nullptr;
    }
}

// Construct with another json
JsonDocument::JsonDocument(JsonDocument& other)
{
    m_pJsonObj = new Poco::Dynamic::Var;
    m_pJsonDoc = new Poco::JSON::Object;
    m_pJsonArr = new Poco::JSON::Array;
    m_pErrMsg = new std::string;

    *(Trans(m_pJsonObj,Poco::Dynamic::Var)) =  *(Trans(other.m_pJsonObj,Poco::Dynamic::Var));
    *(Trans(m_pJsonDoc,Poco::JSON::Object)) =  *(Trans(other.m_pJsonDoc,Poco::JSON::Object));
    *(Trans(m_pJsonArr,Poco::JSON::Array)) =  *(Trans(other.m_pJsonArr,Poco::JSON::Array));
    *m_pErrMsg = *(other.m_pErrMsg);
}

// Copy construction
JsonDocument::JsonDocument(const JsonDocument& other)
{
    m_pJsonObj = new Poco::Dynamic::Var;
    m_pJsonDoc = new Poco::JSON::Object;
    m_pJsonArr = new Poco::JSON::Array;
    m_pErrMsg = new std::string;

    *(Trans(m_pJsonObj,Poco::Dynamic::Var)) =  *(Trans(other.m_pJsonObj,Poco::Dynamic::Var));
    *(Trans(m_pJsonDoc,Poco::JSON::Object)) =  *(Trans(other.m_pJsonDoc,Poco::JSON::Object));
    *(Trans(m_pJsonArr,Poco::JSON::Array)) =  *(Trans(other.m_pJsonArr,Poco::JSON::Array));
    *m_pErrMsg = *(other.m_pErrMsg);
}

// Assigment of json
JsonDocument& JsonDocument::operator=(const JsonDocument& other)
{
    if(this != &other)
    {
        if (m_pJsonObj)
        {
            delete Trans(m_pJsonObj, Poco::Dynamic::Var);
            m_pJsonObj = nullptr;
        }
        
        if (m_pJsonDoc)
        {
            delete Trans(m_pJsonDoc, Poco::JSON::Object);
            m_pJsonDoc = nullptr;
        }

        if (m_pJsonArr)
        {
            delete Trans(m_pJsonArr, Poco::JSON::Array);
            m_pJsonArr = nullptr;
        }
        if (m_pErrMsg)
        {
            delete m_pErrMsg;
            m_pErrMsg = nullptr;
        }
        m_pJsonObj = new Poco::Dynamic::Var;
        m_pJsonDoc = new Poco::JSON::Object;
        m_pJsonArr = new Poco::JSON::Array;
        m_pErrMsg = new std::string;

        *(Trans(m_pJsonObj,Poco::Dynamic::Var)) =  *(Trans(other.m_pJsonObj,Poco::Dynamic::Var));
        *(Trans(m_pJsonDoc,Poco::JSON::Object)) =  *(Trans(other.m_pJsonDoc,Poco::JSON::Object));
        *(Trans(m_pJsonArr,Poco::JSON::Array)) =  *(Trans(other.m_pJsonArr,Poco::JSON::Array));
        *m_pErrMsg = *(other.m_pErrMsg);
    }
    return *this;
}

// Get err msg
std::string JsonDocument::GetErrMsg()
{
    if(m_pErrMsg == nullptr)
    {
        return "";
    }

    return *m_pErrMsg;
}

// Set err msg
void JsonDocument::SetErrMsg(std::string strMsg)
{
    if (m_pErrMsg == nullptr)
    {
        m_pErrMsg = new std::string;
    }

    *m_pErrMsg = strMsg;
}

// Parse from string
JsonDocument JsonDocument::FromJson(std::string strJsonData)
{
    if(strJsonData.empty())
    {
        return JsonDocument();
    }
    JsonDocument CurJson;
    try
    {
        Poco::JSON::Parser JsonParser;
        Poco::Dynamic::Var JsonData = JsonParser.parse(strJsonData);

        Poco::Dynamic::Var& value = *(Trans(CurJson.m_pJsonObj,Poco::Dynamic::Var));
        value = JsonData;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err Happend:" << e.displayText() << std::endl;
        CurJson.SetErrMsg(e.displayText());
    }
    return CurJson;
}

// Parse from json file
JsonDocument JsonDocument::FromJsonFile(std::string strJsonFilePath)
{
    if(strJsonFilePath.empty())
    {
        return JsonDocument();
    }
    std::ifstream fStreamer(strJsonFilePath);
    if(!fStreamer.is_open())
    {
        fStreamer.open(strJsonFilePath,std::ios::binary|std::ios::in);
    }
    JsonDocument CurJson;
    try
    {
        Poco::JSON::Parser JsonParser;
        Poco::Dynamic::Var JsonData = JsonParser.parse(fStreamer);

        Poco::Dynamic::Var &value = *(Trans(CurJson.m_pJsonObj, Poco::Dynamic::Var));
        value = JsonData;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err Happened:" << e.displayText() << std::endl;
         CurJson.SetErrMsg(e.displayText());
    }
    fStreamer.close();
    return CurJson;
}

// Dump to json string
std::string JsonDocument::ToJson()
{
    if(m_pJsonObj == nullptr)
    {
        return "";
    }
    std::string strJsonData = "";
    try
    {
        Poco::Dynamic::Var &value = *(Trans(m_pJsonObj, Poco::Dynamic::Var));

        if (value.isArray())
        {
            Poco::JSON::Array &arr = *(Trans(m_pJsonArr, Poco::JSON::Array));
            std::ostringstream os;
            arr.stringify(os);
            strJsonData = os.str();
        }
        else
        {
            Poco::JSON::Object &obj = *(Trans(m_pJsonDoc, Poco::JSON::Object));
            std::ostringstream os;
            obj.stringify(os);
            strJsonData = os.str();
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err Happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return strJsonData;
}

// Dump to json file
bool JsonDocument::ToJsonFile(std::string strJsonFilePath)
{
    if(strJsonFilePath.empty())
    {
        return false;
    }
    if(m_pJsonObj == nullptr)
    {
        return false;
    }
    std::string strJsonData = "";
    try
    {
        Poco::Dynamic::Var &value = *(Trans(m_pJsonObj, Poco::Dynamic::Var));

        if (value.isArray())
        {
            Poco::JSON::Array &arr = *(Trans(m_pJsonArr, Poco::JSON::Array));
            std::ostringstream os;
            arr.stringify(os);
            strJsonData = os.str();
        }
        else
        {
            Poco::JSON::Object &obj = *(Trans(m_pJsonDoc, Poco::JSON::Object));
            std::ostringstream os;
            obj.stringify(os);
            strJsonData = os.str();
        }
    
        std::ofstream ofstreamer(strJsonFilePath);
        if(!ofstreamer.is_open())
        {
            ofstreamer.open(strJsonFilePath,std::ios::binary|std::ios::out);
        }
        ofstreamer << strJsonData;
        ofstreamer.close();
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err Happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return true;
}

// Is array
bool JsonDocument::IsArray()
{
    if(m_pJsonObj == nullptr)
    {
        return true;
    }
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        if(data.type() == typeid(Poco::JSON::Array::Ptr))
        {
            return true;
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err Happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}

// Is obj
bool JsonDocument::IsObject()
{
    if(m_pJsonObj == nullptr)
    {
        return true;
    }
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        if(data.type() == typeid(Poco::JSON::Object::Ptr))
        {
            return true;
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err Happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}

// Is null json
bool JsonDocument::IsNull()
{
    if(m_pJsonObj == nullptr)
    {
        return true;
    }
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        if(data.type() == typeid(Poco::JSON::Object::Ptr))
        {
            Poco::JSON::Object::Ptr pObj = data.extract<Poco::JSON::Object::Ptr>();
            return pObj.isNull();
        }
        else if(data.type() == typeid(Poco::JSON::Array::Ptr))
        {
            Poco::JSON::Array::Ptr pArr = data.extract<Poco::JSON::Array::Ptr>();
            return pArr.isNull();
        }
        if(data.isEmpty())
        {
            return true;
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err Happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}

// Is empty json
bool JsonDocument::IsEmpty()
{
    if(m_pJsonObj == nullptr)
    {
        return true;
    }
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        if(data.isEmpty())
        {
            return true;
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}

// Is contain the key
bool JsonDocument::IsContainKey(std::string strKey)
{
    if(strKey.empty())
    {
        return false;
    }
    if(IsEmpty())
    {
        return false;
    }
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        Poco::JSON::Object::Ptr pObj = data.extract<Poco::JSON::Object::Ptr>();
        if(pObj->has(strKey))
        {
            return true;
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}

// Get all root's keys
bool JsonDocument::GetAllKeys(std::vector<std::string>& vKeyTable)
{
    if(IsEmpty())
    {
        return false;
    }
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        Poco::JSON::Object::Ptr pObj = data.extract<Poco::JSON::Object::Ptr>();
        pObj->getNames(vKeyTable);
        return true;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}

// Set obj
bool JsonDocument::SetKeyValue(std::string strKey, JsonDocument &obj)
{
    if(strKey.empty())
    {
        return false;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        Poco::JSON::Object &obj_cur = *(Trans(m_pJsonDoc, Poco::JSON::Object));

        Poco::Dynamic::Var &data_other = *(Trans(obj.m_pJsonObj, Poco::Dynamic::Var));
        obj_cur.set(strKey, data_other);

        data = obj_cur;
        return true;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}

// Set string
bool JsonDocument::SetKeyValue(std::string strKey, std::string strData)
{
    if(strKey.empty())
    {
        return false;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        
        Poco::JSON::Object &obj_cur = *(Trans(m_pJsonDoc, Poco::JSON::Object));
        obj_cur.set(strKey,strData);

        data=obj_cur;
        return true;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}

// Set string
bool JsonDocument::SetKeyValue(std::string strKey, const char* pData)
{
    if(pData == nullptr)
    {
        return false;
    }
    if(strKey.empty())
    {
        return false;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        
        Poco::JSON::Object &obj_cur = *(Trans(m_pJsonDoc, Poco::JSON::Object));
        obj_cur.set(strKey,pData);

        data=obj_cur;
        return true;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}

// Set int
bool JsonDocument::SetKeyValue(std::string strKey, int iValue)
{
    if(strKey.empty())
    {
        return false;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        
        Poco::JSON::Object &obj_cur = *(Trans(m_pJsonDoc, Poco::JSON::Object));
        obj_cur.set(strKey,iValue);

        data=obj_cur;
        return true;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}

// Set unsigned int
bool JsonDocument::SetKeyValue(std::string strKey, unsigned int uValue)
{
    if(strKey.empty())
    {
        return false;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        
        Poco::JSON::Object &obj_cur = *(Trans(m_pJsonDoc, Poco::JSON::Object));
        obj_cur.set(strKey,uValue);

        data=obj_cur;
        return true;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}

// Set long
bool JsonDocument::SetKeyValue(std::string strKey, long lValue)
{
    if(strKey.empty())
    {
        return false;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        
        Poco::JSON::Object &obj_cur = *(Trans(m_pJsonDoc, Poco::JSON::Object));
        obj_cur.set(strKey,lValue);

        data=obj_cur;
        return true;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}

// Set long long
bool JsonDocument::SetKeyValue(std::string strKey, long long llValue)
{
    if(strKey.empty())
    {
        return false;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        
        Poco::JSON::Object &obj_cur = *(Trans(m_pJsonDoc, Poco::JSON::Object));
        obj_cur.set(strKey,llValue);

        data=obj_cur;
        return true;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}

// Set unsigend long long
bool JsonDocument::SetKeyValue(std::string strKey, unsigned long long ullValue)
{
    if(strKey.empty())
    {
        return false;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        
        Poco::JSON::Object &obj_cur = *(Trans(m_pJsonDoc, Poco::JSON::Object));
        obj_cur.set(strKey,ullValue);

        data=obj_cur;
        return true;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}

// Set double
bool JsonDocument::SetKeyValue(std::string strKey, double dValue)
{
    if(strKey.empty())
    {
        return false;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        
        Poco::JSON::Object &obj_cur = *(Trans(m_pJsonDoc, Poco::JSON::Object));
        obj_cur.set(strKey,dValue);

        data=obj_cur;
        return true;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}

// Set bool
bool JsonDocument::SetKeyValue(std::string strKey, bool bValue)
{
    if(strKey.empty())
    {
        return false;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        
        Poco::JSON::Object &obj_cur = *(Trans(m_pJsonDoc, Poco::JSON::Object));
        obj_cur.set(strKey,bValue);

        data=obj_cur;
        return true;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}

// Set short 
bool JsonDocument::SetKeyValue(std::string strKey, short sValue)
{
    if(strKey.empty())
    {
        return false;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        
        Poco::JSON::Object &obj_cur = *(Trans(m_pJsonDoc, Poco::JSON::Object));
        obj_cur.set(strKey,sValue);

        data=obj_cur;
        return true;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}

// Set unsigned short
bool JsonDocument::SetKeyValue(std::string strKey, unsigned short usValue)
{
    if(strKey.empty())
    {
        return false;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        
        Poco::JSON::Object &obj_cur = *(Trans(m_pJsonDoc, Poco::JSON::Object));
        obj_cur.set(strKey,usValue);

        data=obj_cur;
        return true;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}

// Append the obj
void JsonDocument::Append(JsonDocument &obj)
{
    if(m_pJsonObj == nullptr)
    {
        return;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        Poco::JSON::Array &arr_cur = *(Trans(m_pJsonArr, Poco::JSON::Array));

        Poco::Dynamic::Var &data_other = *(Trans(obj.m_pJsonObj, Poco::Dynamic::Var));
        arr_cur.add(data_other);

        data = arr_cur;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
}

// Append string
void JsonDocument::Append(std::string strData)
{
    if(m_pJsonObj == nullptr)
    {
        return;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));

        Poco::JSON::Array &arr_cur = *(Trans(m_pJsonArr, Poco::JSON::Array));
        arr_cur.add(strData);

        data = arr_cur;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
}

// Append string
void JsonDocument::Append(const char* pData)
{
    if(pData == nullptr)
    {
        return;
    }
    if(m_pJsonObj == nullptr)
    {
        return;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));

        Poco::JSON::Array &arr_cur = *(Trans(m_pJsonArr, Poco::JSON::Array));
        arr_cur.add(pData);

        data = arr_cur;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
}

// Append the int
void JsonDocument::Append(int iValue)
{
    if(m_pJsonObj == nullptr)
    {
        return;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        
        Poco::JSON::Array &arr_cur = *(Trans(m_pJsonArr, Poco::JSON::Array));
        arr_cur.add(iValue);

        data = arr_cur;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
}

// Append the unsigend int
void JsonDocument::Append(unsigned int uiValue)
{
    if(m_pJsonObj == nullptr)
    {
        return;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        
        Poco::JSON::Array &arr_cur = *(Trans(m_pJsonArr, Poco::JSON::Array));
        arr_cur.add(uiValue);

        data = arr_cur;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
}

// Append the long 
void JsonDocument::Append(long lValue)
{
    if(m_pJsonObj == nullptr)
    {
        return;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        
        Poco::JSON::Array &arr_cur = *(Trans(m_pJsonArr, Poco::JSON::Array));
        arr_cur.add(lValue);

        data = arr_cur;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
}

// Append the long long
void JsonDocument::Append(long long llValue)
{
    if(m_pJsonObj == nullptr)
    {
        return;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        
        Poco::JSON::Array &arr_cur = *(Trans(m_pJsonArr, Poco::JSON::Array));
        arr_cur.add(llValue);

        data = arr_cur;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
}

// Append the unsigned long long
void JsonDocument::Append(unsigned long long ullValue)
{
    if(m_pJsonObj == nullptr)
    {
        return;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        
        Poco::JSON::Array &arr_cur = *(Trans(m_pJsonArr, Poco::JSON::Array));
        arr_cur.add(ullValue);

        data = arr_cur;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
}

// Append the double 
void JsonDocument::Append(double dValue)
{
    if(m_pJsonObj == nullptr)
    {
        return;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        
        Poco::JSON::Array &arr_cur = *(Trans(m_pJsonArr, Poco::JSON::Array));
        arr_cur.add(dValue);

        data = arr_cur;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
}

// Appened the bool
void JsonDocument::Append(bool bValue)
{
    if(m_pJsonObj == nullptr)
    {
        return;
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        
        Poco::JSON::Array &arr_cur = *(Trans(m_pJsonArr, Poco::JSON::Array));
        arr_cur.add(bValue);

        data = arr_cur;
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
}

// Get size of json array
int JsonDocument::Size()
{
    if(m_pJsonObj == nullptr)
    {
        return -1;
    }
    int iSize = 0;
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        if(data.type() == typeid(Poco::JSON::Object::Ptr))
        {
            Poco::JSON::Object::Ptr pObj = data.extract<Poco::JSON::Object::Ptr>();
            return pObj->size();
        }
        else if(data.type() == typeid(Poco::JSON::Array::Ptr))
        {
            Poco::JSON::Array::Ptr pArr = data.extract<Poco::JSON::Array::Ptr>();
            return pArr->size();
        }
        iSize = data.size();
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return iSize;
}

// Get obj
JsonDocument JsonDocument::GetKeyValue(std::string strKey)
{
    if(strKey.empty())
    {
        return *this;
    }
    if(m_pJsonObj == nullptr)
    {
        return *this;
    }
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        if(data.type() == typeid(Poco::JSON::Object::Ptr))
        {
            Poco::JSON::Object::Ptr pObj = data.extract<Poco::JSON::Object::Ptr>();

            JsonDocument NewJson;
            Poco::Dynamic::Var& NewData = *(Trans(NewJson.m_pJsonObj,Poco::Dynamic::Var));
            NewData = pObj->get(strKey);
            return NewJson;
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return *this;
}

// Get obj
JsonDocument JsonDocument::GetKeyValue(const char* pKey)
{
    if(pKey == nullptr)
    {
        return *this;
    }
    if(m_pJsonObj == nullptr)
    {
        return *this;
    }
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        if(data.type() == typeid(Poco::JSON::Object::Ptr))
        {
            Poco::JSON::Object::Ptr pObj = data.extract<Poco::JSON::Object::Ptr>();

            JsonDocument NewJson;
            Poco::Dynamic::Var& NewData = *(Trans(NewJson.m_pJsonObj,Poco::Dynamic::Var));
            NewData = pObj->get(pKey);
            return NewJson;
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return *this;
}

// Get array element
JsonDocument JsonDocument::operator[](int iIndex)
{
    if(iIndex < 0)
    {
        return *this;
    }
    if(m_pJsonObj == nullptr)
    {
        return *this;
    }
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        if(data.type() == typeid(Poco::JSON::Array::Ptr))
        {
            Poco::JSON::Array::Ptr pArr = data.extract<Poco::JSON::Array::Ptr>();

            JsonDocument NewJson;
            Poco::Dynamic::Var& NewData = *(Trans(NewJson.m_pJsonObj,Poco::Dynamic::Var));
            NewData = pArr->get(iIndex);
            return NewJson;
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return *this;
}

// Get data type
const std::type_info& JsonDocument::GetDataType()
{
     if(m_pJsonObj == nullptr)
    {
        return typeid(int);
    }
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        return data.type();
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return typeid(int);
}

// Is string
bool JsonDocument::IsString()
{
    if(m_pJsonObj == nullptr)
    {
        return false;
    }
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        if(data.isString())
        {
            return true;
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}

// Is short
bool JsonDocument::IsShort()
{
    if(m_pJsonObj == nullptr)
    {
        return false;
    }
    Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
    if(data.type() == typeid(short))
    {
        return true;
    }
    return false;
}

// Is unsigned short
bool JsonDocument::IsUShort()
{
    if(m_pJsonObj == nullptr)
    {
        return false;
    }
    Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
    if(data.type() == typeid(unsigned short))
    {
        return true;
    }
    return false;
}

// Is int
bool JsonDocument::IsInt()
{
    if(m_pJsonObj == nullptr)
    {
        return false;
    }
    Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
    if(data.type() == typeid(int))
    {
        return true;
    }
    return false;
}

// Is uint
bool JsonDocument::IsUint()
{
    if(m_pJsonObj == nullptr)
    {
        return false;
    }
    Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
    if(data.type() == typeid(unsigned int))
    {
        return true;
    }
    return false;
}

// Is long 
bool JsonDocument::IsLong()
{
    if(m_pJsonObj == nullptr)
    {
        return false;
    }
    Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
    if(data.type() == typeid(long))
    {
        return true;
    }
    return false;
}

// Is unsigned long
bool JsonDocument::IsULong()
{
    if(m_pJsonObj == nullptr)
    {
        return false;
    }
    Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
    if(data.type() == typeid(unsigned long))
    {
        return true;
    }
    return false;
}

// Is long long
bool JsonDocument::IsLongLong()
{
    if(m_pJsonObj == nullptr)
    {
        return false;
    }
    Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
    if(data.type() == typeid(long long))
    {
        return true;
    }
    return false;
}

// Is unsigned long long
bool JsonDocument::IsULongLong()
{
    if(m_pJsonObj == nullptr)
    {
        return false;
    }
    Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
    if(data.type() == typeid(unsigned long long))
    {
        return true;
    }
    return false;
}

// Is double
bool JsonDocument::IsDouble()
{
    if(m_pJsonObj == nullptr)
    {
        return false;
    }
    Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
    if(data.type() == typeid(double))
    {
        return true;
    }
    return false;
}

// Is bool
bool JsonDocument::IsBool()
{
    if(m_pJsonObj == nullptr)
    {
        return false;
    }
    Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
    if(data.type() == typeid(bool))
    {
        return true;
    }
    return false;
}

// To string
std::string JsonDocument::ToString()
{
    if (m_pJsonObj == nullptr)
    {
        return "";
    }
    try
    {
        Poco::Dynamic::Var &data = *(Trans(m_pJsonObj, Poco::Dynamic::Var));
        return data.toString();
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return "";
}

// To short
short JsonDocument::ToShort()
{
    if(m_pJsonObj == nullptr)
    {
        return 0;
    }
#ifdef _WIN32
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        if(data.type() == typeid(short))
        {
            short sData = data.extract<short>();
            return sData;
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return 0;
#else
    return ToLongLong();
#endif
}

// To unsigned short
unsigned short JsonDocument::ToUnShort()
{
    if(m_pJsonObj == nullptr)
    {
        return 0;
    }
#ifdef _WIN32
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        if(data.type() == typeid(unsigned short))
        {
            unsigned short usData = data.extract<unsigned short>();
            return usData;
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return 0;
#else
    return ToUnLongLong();
#endif
}

// To int
int JsonDocument::ToInt()
{
    if(m_pJsonObj == nullptr)
    {
        return 0;
    }
#ifdef _WIN32
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        if(data.type() == typeid(int))
        {
            int iData = data.extract<int>();
            return iData;
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return 0;
#else
    return ToLongLong();
#endif
}

// To uint
unsigned int JsonDocument::ToUInt()
{
    if(m_pJsonObj == nullptr)
    {
        return 0;
    }
#ifdef _WIN32
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        if(data.type() == typeid(unsigned int))
        {
            unsigned int uData = data.extract<unsigned int>();
            return uData;
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return 0;
#else
    return ToUnLongLong();
#endif
}

// To long 
long JsonDocument::ToLong()
{
    if(m_pJsonObj == nullptr)
    {
        return 0;
    }
#ifdef _WIN32
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        if(data.type() == typeid(long))
        {
            long lData = data.extract<long>();
            return lData;
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return 0;
#else
    return ToLongLong();
#endif
}

// To unsigned long 
unsigned long JsonDocument::ToUnLong()
{
    if(m_pJsonObj == nullptr)
    {
        return 0;
    }
#ifdef _WIN32
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        if(data.type() == typeid(unsigned long))
        {
            unsigned long ulData = data.extract<unsigned long>();
            return ulData;
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return 0;
#else
    return ToUnLongLong();
#endif
}

// To long long
long long JsonDocument::ToLongLong()
{
    if(m_pJsonObj == nullptr)
    {
        return 0;
    }
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        if(data.type() == typeid(long long))
        {
            long long llData = data.extract<long long>();
            return llData;
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return 0;
}

// To unsigned long long
unsigned long long JsonDocument::ToUnLongLong()
{
    if(m_pJsonObj == nullptr)
    {
        return 0;
    }
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        if(data.type() == typeid(unsigned long long))
        {
            unsigned long long ullData = data.extract<unsigned long long>();
            return ullData;
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return 0;
}

// To double
double JsonDocument::ToDouble()
{
    if(m_pJsonObj == nullptr)
    {
        return 0.0f;
    }
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        if(data.type() == typeid(double))
        {
            double dData = data.extract<double>();
            return dData;
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return 0.0f;
}

// To bool 
bool JsonDocument::ToBool()
{
    if(m_pJsonObj == nullptr)
    {
        return false;
    }
    try
    {
        Poco::Dynamic::Var& data = *(Trans(m_pJsonObj,Poco::Dynamic::Var));
        if(data.type() == typeid(bool))
        {
            bool bData = data.extract<bool>();
            return bData;
        }
    }
    catch(Poco::Exception& e)
    {
        std::cerr << "Err happened:" << e.displayText() << std::endl;
        SetErrMsg(e.displayText());
    }
    return false;
}
